// 模特图片集链接爬虫
const { chromium } = require('playwright');
const fs = require('fs');
const readline = require('readline');

// 创建一个读取用户输入的接口
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// 提示用户输入，返回Promise
function promptUser(question) {
  return new Promise((resolve) => {
    rl.question(question, (answer) => {
      resolve(answer);
    });
  });
}

async function main() {
  try {
    // 从环境变量或用户输入获取模特名称
    let modelName = process.env.MODEL_NAME;
    let isHeadless = process.env.HEADLESS_MODE === 'y';
    
    // 如果环境变量未设置，则询问用户
    if (!modelName) {
      modelName = await promptUser('请输入模特名称: ');
      if (!modelName.trim()) {
        console.log('模特名称不能为空');
        rl.close();
        return;
      }
    }
    
    // 如果环境变量未设置无头模式，则询问用户
    if (process.env.HEADLESS_MODE === undefined) {
      const headlessMode = await promptUser('是否使用无头模式(不显示浏览器)？(y/n，默认y): ');
      isHeadless = headlessMode.trim().toLowerCase() !== 'n';
    }
    
    console.log(`将爬取模特 ${modelName} 的所有图片集链接`);
    console.log(`浏览器模式: ${isHeadless ? '无头模式' : '有头模式'}`);
    
    // 创建浏览器实例
    console.log('正在启动浏览器...');
    const browser = await chromium.launch({
      headless: isHeadless
    });
    
    // 创建新页面
    const page = await browser.newPage();
    
    // 访问网站首页
    console.log('正在访问网站首页...');
    await page.goto('http://3c.xy05.my/');
    
    // 等待页面加载完成
    await page.waitForLoadState('networkidle');
    
    // 构造搜索URL并直接访问
    const encodedKeyword = encodeURIComponent(modelName);
    const searchUrl = `http://3c.xy05.my/plus/search/index.asp?keyword=${encodedKeyword}`;
    
    console.log(`正在访问搜索页面: ${searchUrl}`);
    await page.goto(searchUrl);
    
    // 等待搜索结果页面加载
    await page.waitForLoadState('networkidle');
    
    // 收集所有图片集链接
    console.log('收集图片集链接...');
    const links = [];
    
    // 获取当前页面的链接
    let currentPageLinks = await collectLinksFromCurrentPage(page, modelName);
    links.push(...currentPageLinks);
    
    // 检查是否有分页并获取总页数
    let pageInfo = await getPageInfo(page);
    console.log('页面信息:', pageInfo);
    
    // 如果有多页，直接构造各个分页的URL并访问
    if (pageInfo.totalPages > 1) {
      for (let i = 2; i <= pageInfo.totalPages; i++) {
        // 构造分页URL
        let pageUrl = '';
        if (pageInfo.pageUrlPattern) {
          pageUrl = pageInfo.pageUrlPattern.replace('{page}', i);
        } else {
          // 尝试通用分页URL格式
          pageUrl = `${searchUrl}&page=${i}`;
        }
        
        console.log(`正在访问第 ${i} 页: ${pageUrl}`);
        await page.goto(pageUrl);
        await page.waitForLoadState('networkidle');
        
        // 获取该页的链接
        const pageLinks = await collectLinksFromCurrentPage(page, modelName);
        links.push(...pageLinks);
      }
    } else {
      // 备用方案：使用点击下一页按钮的方式
      console.log('使用点击下一页按钮的方式获取分页...');
      let hasNextPage = await hasNextPageLink(page);
      let pageNum = 1;
      
      while (hasNextPage) {
        console.log(`正在处理第 ${pageNum + 1} 页...`);
        
        // 点击下一页
        const clickSuccess = await clickNextPage(page);
        if (!clickSuccess) {
          console.log('无法点击下一页按钮，停止获取分页');
          break;
        }
        
        await page.waitForLoadState('networkidle');
        await page.waitForTimeout(2000);
        
        // 获取下一页的链接
        const nextPageLinks = await collectLinksFromCurrentPage(page, modelName);
        links.push(...nextPageLinks);
        
        // 检查是否还有下一页
        hasNextPage = await hasNextPageLink(page);
        pageNum++;
      }
    }
    
    // 将链接保存到文件
    console.log(`总共收集到 ${links.length} 个图片集链接`);
    saveLinksToFile(links, modelName);
    
    console.log('任务完成！');
    
    // 关闭浏览器
    await browser.close();
    
    // 关闭readline接口
    rl.close();
  } catch (error) {
    console.error('发生错误:', error);
    rl.close();
  }
}

// 获取分页信息
async function getPageInfo(page) {
  try {
    return await page.evaluate(() => {
      const pageInfo = {
        currentPage: 1,
        totalPages: 1,
        pageUrlPattern: null
      };
      
      // 尝试从分页元素获取总页数
      const pageSelectors = [
        '.pagelist', 
        '.page',
        '.pagination'
      ];
      
      let paginationElement = null;
      
      for (const selector of pageSelectors) {
        const element = document.querySelector(selector);
        if (element) {
          paginationElement = element;
          break;
        }
      }
      
      if (paginationElement) {
        // 获取所有页码链接
        const pageLinks = paginationElement.querySelectorAll('a');
        if (pageLinks.length > 0) {
          // 尝试找到最后一个数字链接作为总页数
          const pageNumbers = [];
          
          for (const link of pageLinks) {
            const text = link.textContent.trim();
            const pageNum = parseInt(text);
            if (!isNaN(pageNum)) {
              pageNumbers.push(pageNum);
              
              // 同时获取URL模式
              if (pageInfo.pageUrlPattern === null && link.href.includes('page=')) {
                const url = new URL(link.href);
                url.searchParams.set('page', '{page}');
                pageInfo.pageUrlPattern = url.toString();
              }
            }
          }
          
          if (pageNumbers.length > 0) {
            pageInfo.totalPages = Math.max(...pageNumbers);
          }
          
          // 如果没有找到页码，但有"下一页"按钮，则至少有2页
          if (pageInfo.totalPages === 1) {
            for (const link of pageLinks) {
              if (link.textContent.includes('下一页') || 
                  link.textContent.includes('Next') || 
                  link.title === '下一页' ||
                  link.className.includes('next')) {
                pageInfo.totalPages = 2;
                break;
              }
            }
          }
        }
      }
      
      return pageInfo;
    });
  } catch (error) {
    console.error('获取分页信息时出错:', error);
    return { currentPage: 1, totalPages: 1, pageUrlPattern: null };
  }
}

// 收集当前页面的链接
async function collectLinksFromCurrentPage(page, keyword) {
  try {
    // 获取页面上所有的链接元素
    console.log('尝试获取页面上的链接...');
    
    // 使用不同的选择器尝试获取链接
    const links = await page.evaluate((searchKeyword) => {
      const results = [];
      // 尝试多种可能的选择器来适应网站结构
      const selectors = [
        'li a', 
        '.piclist a', 
        '.article-list a',
        '.search-list a',
        'a[href*="/view/"]',
        'a[href*=".html"]',
        '.c10 a',
        // 更多具体的选择器
        '.article_item a',
        '.pic_item a',
        '.item a',
        'div.item h2 a'
      ];
      
      for (const selector of selectors) {
        try {
          const elements = document.querySelectorAll(selector);
          
          if (elements.length > 0) {
            for (const el of elements) {
              if (el.href && (el.href.includes('/view/') || el.href.includes('.html') || el.href.includes('/XiuRen/'))) {
                // 只收集包含关键词的链接
                const linkText = el.textContent.trim() || el.getAttribute('title') || '';
                const href = el.href;
                
                if (linkText.includes(searchKeyword) || 
                    (linkText.includes('模特') && href.includes(searchKeyword)) ||
                    (href.includes('XiuRen') && linkText.length > 5)) {
                  results.push({
                    title: linkText,
                    url: href
                  });
                }
              }
            }
          }
        } catch (err) {
          console.error(`选择器 ${selector} 出错:`, err);
        }
      }
      
      return results;
    }, keyword);
    
    // 去重
    const uniqueLinks = Array.from(new Set(links.map(link => link.url)))
      .map(url => links.find(link => link.url === url));
    
    console.log(`当前页面收集到 ${uniqueLinks.length} 个链接`);
    return uniqueLinks;
  } catch (error) {
    console.error('收集链接时出错:', error);
    return [];
  }
}

// 检查是否有下一页
async function hasNextPageLink(page) {
  try {
    const result = await page.evaluate(() => {
      // 检查各种可能的下一页按钮
      const nextPageSelectors = [
        '.pagelist a',
        '.page a',
        '.pagination a',
        'a.next',
        'a[title="下一页"]',
        'a:contains("下一页")',
        'a.nextpage'
      ];
      
      for (const selector of nextPageSelectors) {
        try {
          const elements = document.querySelectorAll(selector);
          
          for (const el of elements) {
            if (el.textContent.includes('下一页') || 
                el.textContent.includes('Next') || 
                el.title === '下一页' ||
                el.className.includes('next')) {
              return { hasNext: true, html: el.outerHTML };
            }
          }
        } catch (err) {
          console.error(`下一页选择器 ${selector} 出错`);
        }
      }
      
      return { hasNext: false };
    });
    
    if (result.hasNext) {
      console.log('找到下一页按钮:', result.html);
    } else {
      console.log('没有找到下一页按钮');
    }
    
    return result.hasNext;
  } catch (error) {
    console.error('检查下一页链接时出错:', error);
    return false;
  }
}

// 点击下一页
async function clickNextPage(page) {
  try {
    // 1. 尝试使用JavaScript点击
    const jsClicked = await page.evaluate(() => {
      // 尝试各种可能的下一页按钮
      const nextPageSelectors = [
        '.pagelist a',
        '.page a',
        '.pagination a',
        'a.next',
        'a[title="下一页"]'
      ];
      
      for (const selector of nextPageSelectors) {
        try {
          const elements = document.querySelectorAll(selector);
          
          for (const el of elements) {
            if (el.textContent.includes('下一页') || 
                el.textContent.includes('Next') || 
                el.title === '下一页' ||
                el.className.includes('next')) {
              console.log('JavaScript点击下一页按钮');
              el.click();
              return true;
            }
          }
        } catch (err) {
          console.error(`点击下一页选择器 ${selector} 出错`);
        }
      }
      
      return false;
    });
    
    if (jsClicked) {
      console.log('已通过JavaScript点击下一页按钮');
      await page.waitForTimeout(2000);
      return true;
    }
    
    // 2. 尝试使用Playwright的方法点击
    console.log('尝试使用Playwright点击下一页按钮');
    const nextButtonSelectors = [
      '.pagelist a:has-text("下一页")',
      '.page a:has-text("下一页")',
      '.pagination a:has-text("下一页")',
      'a.next',
      'a[title="下一页"]'
    ];
    
    for (const selector of nextButtonSelectors) {
      try {
        const isVisible = await page.isVisible(selector).catch(() => false);
        if (isVisible) {
          console.log(`找到可见的下一页按钮: ${selector}`);
          await page.click(selector);
          await page.waitForTimeout(2000);
          return true;
        }
      } catch (err) {
        console.error(`Playwright点击选择器 ${selector} 出错:`, err);
      }
    }
    
    // 3. 尝试获取下一页链接并直接导航
    const nextPageUrl = await page.evaluate(() => {
      const nextPageSelectors = [
        '.pagelist a',
        '.page a',
        '.pagination a',
        'a.next',
        'a[title="下一页"]'
      ];
      
      for (const selector of nextPageSelectors) {
        try {
          const elements = document.querySelectorAll(selector);
          
          for (const el of elements) {
            if (el.textContent.includes('下一页') || 
                el.textContent.includes('Next') || 
                el.title === '下一页' ||
                el.className.includes('next')) {
              return el.href;
            }
          }
        } catch (err) {}
      }
      
      return null;
    });
    
    if (nextPageUrl) {
      console.log(`直接导航到下一页: ${nextPageUrl}`);
      await page.goto(nextPageUrl);
      await page.waitForTimeout(2000);
      return true;
    }
    
    console.log('无法找到下一页按钮');
    return false;
  } catch (error) {
    console.error('点击下一页时出错:', error);
    return false;
  }
}

// 保存链接到文件
function saveLinksToFile(links, modelName) {
  // 如果没有收集到链接，则记录错误信息
  if (links.length === 0) {
    console.error('没有收集到任何链接，请检查网站结构或选择器');
    return;
  }
  
  // 过滤掉不包含模特名字的链接
  const filteredLinks = links.filter(link => {
    return link.title.includes(modelName) || 
           (link.title.includes('模特') && link.url.includes(modelName));
  });
  
  console.log(`过滤后剩余 ${filteredLinks.length} 个链接`);
  
  // 格式化链接内容
  const content = filteredLinks.map(link => `${link.title}\n${link.url}\n`).join('\n');
  const filename = `${modelName}_图片集链接.txt`;
  
  fs.writeFileSync(filename, content, 'utf8');
  console.log(`链接已保存到文件: ${filename}`);
}

// 执行主函数
main().catch(console.error); 